<!DOCTYPE html>
<html lang=zh-CN>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta property="og:description" content="samuel-24276的博客">
    <meta property="og:type" content="website">
    <meta name="description" content="samuel-24276的博客">
    <meta name="keyword"  content="aircloud">
    <link rel="shortcut icon" href="/myblog/img/favicon.ico">

    <title>
        
        进程间通信（IPC） - samuel-24276的博客 | samuel-24276&#39;s Blog
        
    </title>

    <!-- Custom CSS -->
    
<link rel="stylesheet" href="/myblog/css/aircloud.css">

    
<link rel="stylesheet" href="/myblog/css/gitment.css">

    <!--<link rel="stylesheet" href="https://imsun.github.io/gitment/style/default.css">-->
    <link href="//at.alicdn.com/t/font_620856_28hi1hpxx24.css" rel="stylesheet" type="text/css">
    <!-- ga & ba script hoook -->
    <script></script>
<meta name="generator" content="Hexo 7.1.1"></head>

<body>

<div class="site-nav-toggle" id="site-nav-toggle">
    <button>
        <span class="btn-bar"></span>
        <span class="btn-bar"></span>
        <span class="btn-bar"></span>
    </button>
</div>

<div class="index-about">
    <i> Like what you do, do what you like </i>
</div>

<div class="index-container">
    
    <div class="index-left">
        
<div class="nav" id="nav">
    <div class="avatar-name">
        <div class="avatar ">
            <img src="/myblog/img/avatar.jpg" />
        </div>
        <div class="name">
            <i>samuel-24276</i>
        </div>
    </div>
    <div class="contents" id="nav-content">
        <ul>
            <li >
                <a href="/myblog/">
                    <i class="iconfont icon-shouye1"></i>
                    <span>主页</span>
                </a>
            </li>
            <li >
                <a href="/myblog/tags">
                    <i class="iconfont icon-biaoqian1"></i>
                    <span>标签</span>
                </a>
            </li>
            <li >
                <a href="/myblog/archives">
                    <i class="iconfont icon-guidang2"></i>
                    <span>存档</span>
                </a>
            </li>
            <li >
                <a href="/myblog/collect/">
                    <i class="iconfont icon-shoucang1"></i>
                    <span>收藏</span>
                </a>
            </li>
            <li >
                <a href="/myblog/about/">
                    <i class="iconfont icon-guanyu2"></i>
                    <span>关于</span>
                </a>
            </li>
            
            <li>
                <a id="search">
                    <i class="iconfont icon-sousuo1"></i>
                    <span>搜索</span>
                </a>
            </li>
            
        </ul>
    </div>
    
        <div id="toc" class="toc-article">
    <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1IPC"><span class="toc-text">进程间通信IPC</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E8%BF%B0"><span class="toc-text">简述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%80%9A%E4%BF%A1%E7%9B%AE%E7%9A%84"><span class="toc-text">通信目的</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F"><span class="toc-text">通信方式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AE%A1%E9%81%93%EF%BC%88pipe%EF%BC%89%EF%BC%9A"><span class="toc-text">管道（pipe）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9C%89%E5%90%8D%E7%AE%A1%E9%81%93%EF%BC%88named-pipe%EF%BC%89%EF%BC%9A"><span class="toc-text">有名管道（named pipe）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BF%A1%E5%8F%B7%E9%87%8F%EF%BC%88semophore%EF%BC%89%EF%BC%9A"><span class="toc-text">信号量（semophore）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%EF%BC%88message-queue%EF%BC%89%EF%BC%9A"><span class="toc-text">消息队列（message queue）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BF%A1%E5%8F%B7%EF%BC%88signal%EF%BC%89%EF%BC%9A"><span class="toc-text">信号（signal）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98%EF%BC%88shared-memory%EF%BC%89%EF%BC%9A"><span class="toc-text">共享内存（shared memory）：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A5%97%E6%8E%A5%E5%AD%97%EF%BC%88socket%EF%BC%89%EF%BC%9A"><span class="toc-text">套接字（socket）：</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Qt%E8%BF%9B%E7%A8%8B%E9%80%9A%E4%BF%A1"><span class="toc-text">Qt进程通信</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#TCP-IP"><span class="toc-text">TCP&#x2F;IP</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Shared-Memory"><span class="toc-text">Shared Memory</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#D-Bus"><span class="toc-text">D-Bus</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#QProcess"><span class="toc-text">QProcess</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Session-Management"><span class="toc-text">Session Management</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Qt%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%E4%B9%8BWindows%E6%B6%88%E6%81%AF"><span class="toc-text">Qt进程间通信之Windows消息</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E8%BF%B0-1"><span class="toc-text">简述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%88%E6%9E%9C"><span class="toc-text">效果</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF"><span class="toc-text">发送消息</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%B1%BB%E5%9E%8B%E4%B8%8E%E6%8E%A5%E6%94%B6%E7%AA%97%E4%BD%93"><span class="toc-text">自定义类型与接收窗体</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8F%91%E9%80%81%E6%95%B0%E6%8D%AE"><span class="toc-text">发送数据</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF"><span class="toc-text">接收消息</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AE%BE%E7%BD%AE%E6%A0%87%E9%A2%98"><span class="toc-text">设置标题</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%87%8D%E5%86%99nativeEvent"><span class="toc-text">重写nativeEvent</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Qt%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%E4%B9%8B%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98"><span class="toc-text">Qt进程间通信之共享内存</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E8%BF%B0-2"><span class="toc-text">简述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#QSharedMemory"><span class="toc-text">QSharedMemory</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#QSystemSemaphore"><span class="toc-text">QSystemSemaphore</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9"><span class="toc-text">注意事项</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8A%A0%E8%BD%BD%E8%BF%9B%E5%86%85%E5%AD%98"><span class="toc-text">加载进内存</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AF%B4%E6%98%8E"><span class="toc-text">说明</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%9E%E7%8E%B0"><span class="toc-text">实现</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%8E%E5%86%85%E5%AD%98%E4%B8%AD%E8%AF%BB%E5%8F%96"><span class="toc-text">从内存中读取</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AF%B4%E6%98%8E-1"><span class="toc-text">说明</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%9E%E7%8E%B0-1"><span class="toc-text">实现</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Qt%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%E4%B9%8BQProcess"><span class="toc-text">Qt进程间通信之QProcess</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E8%BF%B0-3"><span class="toc-text">简述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E5%90%AF%E5%8A%A8"><span class="toc-text">命令行参数启动</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%AF%BB%E5%8F%96"><span class="toc-text">命令行读取</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AF%B4%E6%98%8E-2"><span class="toc-text">说明</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%9E%E7%8E%B0-2"><span class="toc-text">实现</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Qt%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%E4%B9%8BTCP-IP"><span class="toc-text">Qt进程间通信之TCP&#x2F;IP</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E8%BF%B0-4"><span class="toc-text">简述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#QtNetwork"><span class="toc-text">QtNetwork</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Server"><span class="toc-text">Server</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Client"><span class="toc-text">Client</span></a></li></ol></li></ol>
</div>
    
</div>


<div class="search-field" id="search-field">
    <div class="search-bg" id="search-bg"></div>
    <div class="search-container">
        <div class="search-input">
            <span id="esc-search"> <i class="icon-fanhui iconfont"></i></span>
            <input id="search-input"/>
            <span id="begin-search">搜索</span>
        </div>
        <div class="search-result-container" id="search-result-container">

        </div>
    </div>
</div>

        <div class="index-about-mobile">
            <i> Like what you do, do what you like </i>
        </div>
    </div>
    
    <div class="index-middle">
        <!-- Main Content -->
        


<div class="post-container">
    <div class="post-title">
        进程间通信（IPC）
    </div>

    <div class="post-meta">
        <span class="attr">发布于：<span>2023-03-11 14:14:21</span></span>
        
        <span class="attr">标签：/
        
        <a class="tag" href="/myblog/tags/#Qt" title="Qt">Qt</a>
        <span>/</span>
        
        <a class="tag" href="/myblog/tags/#进程" title="进程">进程</a>
        <span>/</span>
        
        
        </span>
        <span class="attr">访问：<span id="busuanzi_value_page_pv"></span>
</span>
</span>
    </div>
    <div class="post-content no-indent">
        <p><a target="_blank" rel="noopener" href="https://blog.csdn.net/liang19890820/article/details/50589285">Qt 之进程间通信（IPC）</a></p>
<p>文章来源：<a target="_blank" rel="noopener" href="https://blog.csdn.net/liang19890820/article/details/50589285">Qt 之进程间通信（IPC）</a></p>
<h1 id="进程间通信IPC"><a href="#进程间通信IPC" class="headerlink" title="进程间通信IPC"></a>进程间通信IPC</h1><h2 id="简述"><a href="#简述" class="headerlink" title="简述"></a>简述</h2><p>进程间通信，就是在不同进程之间传播或交换信息。那么不同进程之间存在着什么双方都可以访问的介质呢？<strong>进程的用户空间是互相独立的，一般而言是不能互相访问的，唯一的例外是共享内存区</strong>。但是，系统空间却是“公共场所”，所以内核显然可以提供这样的条件。除此以外，那就是双方都可以访问的外设了。<strong>在这个意义上，两个进程当然也可以通过磁盘上的普通文件交换信息，或者通过“注册表”或其它数据库中的某些表项和记录交换信息</strong>。广义上这也是进程间通信的手段，但是一般都不把这算作“进程间通信”。</p>
<p>进程间通信（IPC-Interprocess communication）是一组编程接口，能够让程序员协调不同的进程，使之能在一个操作系统里同时运行。这使得一个程序能够在同一时间里处理许多用户的要求。因为即使只有一个用户发出要求，也可能导致一个操作系统中多个进程的运行，进程之间必须互相通话。IPC接口就提供了这种可能性。每个IPC方法均有自己的优点和局限性，因此，对于单个程序而言使用所有的IPC方法并不常见。</p>
<h2 id="通信目的"><a href="#通信目的" class="headerlink" title="通信目的"></a>通信目的</h2><p>数据传输：<br>一个进程需要将它的数据发送给另一个进程，发送的数据量在一个字节到几兆字节之间。</p>
<p>共享数据：<br>多个进程想要操作共享数据，一个进程对共享数据的修改，别的进程应该立刻看到。</p>
<p>通知事件：<br>一个进程需要向另一个或一组进程发送消息，通知它（它们）发生了某种事件（如进程终止时要通知父进程）。</p>
<p>资源共享：<br>多个进程之间共享同样的资源。为了作到这一点，需要内核提供锁和同步机制。</p>
<p>进程控制：<br>有些进程希望完全控制另一个进程的执行（如Debug进程），此时控制进程希望能够拦截另一个进程的所有陷入和异常，并能够及时知道它的状态改变。</p>
<p>进程通过与内核及其它进程之间的互相通信来协调它们的行为。<strong>Linux支持多种进程间通信（IPC）机制，信号和管道是其中的两种</strong>。</p>
<h2 id="通信方式"><a href="#通信方式" class="headerlink" title="通信方式"></a>通信方式</h2><h3 id="管道（pipe）："><a href="#管道（pipe）：" class="headerlink" title="管道（pipe）："></a>管道（pipe）：</h3><p>管道是一种半双工的通信方式，数据只能单向流动，而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。</p>
<h3 id="有名管道（named-pipe）："><a href="#有名管道（named-pipe）：" class="headerlink" title="有名管道（named pipe）："></a>有名管道（named pipe）：</h3><p>有名管道也是半双工的通信方式，但是它允许无亲缘关系进程间的通信。</p>
<h3 id="信号量（semophore）："><a href="#信号量（semophore）：" class="headerlink" title="信号量（semophore）："></a>信号量（semophore）：</h3><p>信号量是一个计数器，可以用来控制多个进程对共享资源的访问。它常作为一种锁机制，防止某进程正在访问共享资源时，其它进程也访问该资源。因此，主要作为进程间以及同一进程内不同线程之间的同步手段。</p>
<h3 id="消息队列（message-queue）："><a href="#消息队列（message-queue）：" class="headerlink" title="消息队列（message queue）："></a>消息队列（message queue）：</h3><p>消息队列就是消息的一个链表，存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。</p>
<h3 id="信号（signal）："><a href="#信号（signal）：" class="headerlink" title="信号（signal）："></a>信号（signal）：</h3><p>信号是一种比较复杂的通信方式，用于通知接收进程某个事件已经发生。</p>
<h3 id="共享内存（shared-memory）："><a href="#共享内存（shared-memory）：" class="headerlink" title="共享内存（shared memory）："></a>共享内存（shared memory）：</h3><p>共享内存就是映射一段能被其他进程所访问的内存，这段共享内存由一个进程创建，但多个进程都可以访问。共享内存是最快的IPC方式，它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制，如信号量，配合使用，来实现进程间的同步和通信。</p>
<h3 id="套接字（socket）："><a href="#套接字（socket）：" class="headerlink" title="套接字（socket）："></a>套接字（socket）：</h3><p>套接字也是一种进程间通信机制，与其他通信机制不同的是，它可用于不同机器间的进程通信。</p>
<h1 id="Qt进程通信"><a href="#Qt进程通信" class="headerlink" title="Qt进程通信"></a>Qt进程通信</h1><p>在Qt应用程序中，Qt提供了几个方法来实现进程间通信（IPC）。可以在助手中查找关键字”Inter-Process”进行查找。</p>
<h3 id="TCP-IP"><a href="#TCP-IP" class="headerlink" title="TCP&#x2F;IP"></a>TCP&#x2F;IP</h3><p>跨平台的Qt Network模块提供的类可以让网络编程更加便携和方便。它提供了高级类（例如：QNetworkAccessManager、QFtp）通信，使用特定的应用程序级协议，和较底层的类（例如：QTcpSocket、QTcpServer、QSslSocket）用于实现协议。</p>
<h3 id="Shared-Memory"><a href="#Shared-Memory" class="headerlink" title="Shared Memory"></a>Shared Memory</h3><p>跨平台的QSharedMemory-共享内存类，提供对操作系统的共享内存的实现。它允许多个线程和进程安全访问共享内存段。此外，QSystemSemaphore可以用来控制访问由系统共享的资源，以及进程之间的通信。</p>
<h3 id="D-Bus"><a href="#D-Bus" class="headerlink" title="D-Bus"></a>D-Bus</h3><p>Qt的D-Bus模块是一种可用于使用D-Bus协议实现IPC的唯一Unix库。它将Qt的信号和槽机制延伸到IPC级别，允许由一个进程发出的信号被连接到另一个进程的槽。Qt的D-Bus文档已经详细说明如何使用Qt中的D-Bus模块。</p>
<h3 id="QProcess"><a href="#QProcess" class="headerlink" title="QProcess"></a>QProcess</h3><p>跨平台类QProcess可以用于启动外部程序作为子进程，并与它们进行通信。它提供了用于监测和控制该子进程状态的API。另外，QProcess为从QIODevice继承的子进程提供了输入&#x2F;输出通道。</p>
<h3 id="Session-Management"><a href="#Session-Management" class="headerlink" title="Session Management"></a>Session Management</h3><p>在Linux&#x2F;X11平台上，Qt提供了会话管理的支持。会话允许事件传播到进程，例如，当检测到关机时。进程和应用程序可以执行任何必要的操作，例如：保存打开的文档。</p>
<h1 id="Qt进程间通信之Windows消息"><a href="#Qt进程间通信之Windows消息" class="headerlink" title="Qt进程间通信之Windows消息"></a>Qt进程间通信之Windows消息</h1><h2 id="简述-1"><a href="#简述-1" class="headerlink" title="简述"></a>简述</h2><p>通过上一节的了解，我们可以看出进程通信的方式很多，今天分享下如何利用Windows消息机制来进行不同进程间的通信。</p>
<h2 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h2><p><img src="https://img-blog.csdn.net/20160126205217488"></p>
<h2 id="发送消息"><a href="#发送消息" class="headerlink" title="发送消息"></a>发送消息</h2><h3 id="自定义类型与接收窗体"><a href="#自定义类型与接收窗体" class="headerlink" title="自定义类型与接收窗体"></a>自定义类型与接收窗体</h3><p>包含所需库，定义发送的自定义类型、接收消息的窗体标题。自定义类型可以处理消息过多情况下，对消息的区分，如果不需要也可以去掉。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifdef</span> Q_OS_WIN</span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> comment(lib, <span class="string">&quot;user32.lib&quot;</span>)</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;qt_windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> ULONG_PTR CUSTOM_TYPE = <span class="number">10000</span>;</span><br><span class="line"><span class="type">const</span> QString c_strTitle = <span class="string">&quot;ReceiveMessage&quot;</span>;</span><br></pre></td></tr></table></figure>

<h3 id="发送数据"><a href="#发送数据" class="headerlink" title="发送数据"></a>发送数据</h3><p>点击按钮，进行消息发送。里面的do{…}while用来忽略本窗口，当然自身也可以接受自身的消息。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">onSendMessage</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    HWND hwnd = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="comment">//do</span></span><br><span class="line">    <span class="comment">//&#123;</span></span><br><span class="line">       LPWSTR path = (LPWSTR)c_strTitle.<span class="built_in">utf16</span>();  <span class="comment">//path = L&quot;SendMessage&quot;</span></span><br><span class="line">       hwnd = ::<span class="built_in">FindWindowW</span>(<span class="literal">NULL</span>, path);</span><br><span class="line">    <span class="comment">//&#125; while (hwnd == (HWND)effectiveWinId()); // 忽略自己</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (::<span class="built_in">IsWindow</span>(hwnd))</span><br><span class="line">    &#123;</span><br><span class="line">        QString filename = <span class="built_in">QStringLiteral</span>(<span class="string">&quot;进程通信-Windows消息&quot;</span>);</span><br><span class="line">        QByteArray data = filename.<span class="built_in">toUtf8</span>();</span><br><span class="line"></span><br><span class="line">        COPYDATASTRUCT copydata;</span><br><span class="line">        copydata.dwData = CUSTOM_TYPE;  <span class="comment">// 用户定义数据</span></span><br><span class="line">        copydata.lpData = data.<span class="built_in">data</span>();  <span class="comment">//数据大小</span></span><br><span class="line">        copydata.cbData = data.<span class="built_in">size</span>();  <span class="comment">// 指向数据的指针</span></span><br><span class="line"></span><br><span class="line">        HWND sender = (HWND)<span class="built_in">effectiveWinId</span>();</span><br><span class="line"></span><br><span class="line">        ::<span class="built_in">SendMessage</span>(hwnd, WM_COPYDATA, <span class="built_in">reinterpret_cast</span>&lt;WPARAM&gt;(sender), <span class="built_in">reinterpret_cast</span>&lt;LPARAM&gt;(&amp;copydata));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="接收消息"><a href="#接收消息" class="headerlink" title="接收消息"></a>接收消息</h2><h3 id="设置标题"><a href="#设置标题" class="headerlink" title="设置标题"></a>设置标题</h3><p>这一步很重要，必须与上一步的c_strTitle保持一致，否则会找不到窗体。自定义类型CUSTOM_TYPE也必须保持一致，进行过滤。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">setWindowTitle</span>(<span class="string">&quot;ReceiveMessage&quot;</span>);</span><br></pre></td></tr></table></figure>


<h3 id="重写nativeEvent"><a href="#重写nativeEvent" class="headerlink" title="重写nativeEvent"></a>重写nativeEvent</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">nativeEvent</span><span class="params">(<span class="type">const</span> QByteArray &amp;eventType, <span class="type">void</span> *message, <span class="type">long</span> *result)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MSG *param = <span class="built_in">static_cast</span>&lt;MSG *&gt;(message);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> (param-&gt;message)</span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">case</span> WM_COPYDATA:</span><br><span class="line">    &#123;</span><br><span class="line">        COPYDATASTRUCT *cds = <span class="built_in">reinterpret_cast</span>&lt;COPYDATASTRUCT*&gt;(param-&gt;lParam);</span><br><span class="line">        <span class="keyword">if</span> (cds-&gt;dwData == CUSTOM_TYPE)</span><br><span class="line">        &#123;</span><br><span class="line">            QString strMessage = QString::<span class="built_in">fromUtf8</span>(<span class="built_in">reinterpret_cast</span>&lt;<span class="type">char</span>*&gt;(cds-&gt;lpData), cds-&gt;cbData);</span><br><span class="line">            QMessageBox::<span class="built_in">information</span>(<span class="keyword">this</span>, <span class="built_in">QStringLiteral</span>(<span class="string">&quot;提示&quot;</span>), strMessage);</span><br><span class="line">            *result = <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> QWidget::<span class="built_in">nativeEvent</span>(eventType, message, result);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="Qt进程间通信之共享内存"><a href="#Qt进程间通信之共享内存" class="headerlink" title="Qt进程间通信之共享内存"></a>Qt进程间通信之共享内存</h1><h2 id="简述-2"><a href="#简述-2" class="headerlink" title="简述"></a>简述</h2><p>上一节中，我们分享下如何利用Windows消息机制来进行不同进程间的通信。但是有很多局限性，比如：不能跨平台，而且必须两个进程同时存在才可以，要么进程A发了消息谁接收呢？</p>
<p>下面我们来分享另外一种跨平台的进行间通信的方式-Shared Memory（共享内存）。</p>
<p>Qt提供的基于共享内存的IPC有QSharedMemory类和QSystemSemaphore类，<strong>QSharedMemory可以访问共享内存区域，以及多线程和进程的共享内存区域。而QSystemSemaphore类用于访问系统共享资源，以实现独立进程间的通信</strong>。</p>
<h2 id="QSharedMemory"><a href="#QSharedMemory" class="headerlink" title="QSharedMemory"></a>QSharedMemory</h2><p>QSharedMemory读写内存时，可以使用lock()实现同步。因此，如果同步完成，必须使用unlock()为共享内存区域解锁。</p>
<p>QSharedMemory可以使用attach()访问共享内存。可以通过指定参数来设置共享内存的访问模式。如果使用的是QSharedMemory::ReadOnly模式，则只能通过只读模式访问共享内存。反之，使用QSharedMemory::ReadWrite模式则可以通过读写模式访问共享内存。</p>
<p><strong>QSharedMemory拥有进程并提供可以返回共享内存区域指针的成员函数</strong>。在共享内存区域，成员函数constData()可以通过void类型返回进程正在使用的内存区域指针。创建共享时，QSharedMemory可以以字节为单位分配共享内存区域，还可以通过第二个参数设置函数attach()提供的模式。</p>
<p>QSharedMemory可以设置特定共享内存的固定键。函数setNativeKey()可以设置共享内存对象的键，该函数使用从属平台的共享内存的键进行相关设置。相反，使用函数setKey()可以设置与独立与平台的键。函数setKey()创建与平台本地键（Native Key）映射的键。</p>
<h2 id="QSystemSemaphore"><a href="#QSystemSemaphore" class="headerlink" title="QSystemSemaphore"></a>QSystemSemaphore</h2><p>QSystemSemaphore可以提供普通系统的信号量。信号量使用互斥体，而互斥体只可以使用1次锁定（Block）。因此，QSemaphore类不能对有效资源使用多线程，而QSystemSemaphore类可以在多进程或多线程中实现。</p>
<p><strong>QSystemSemaphore与QSemaphore类不同，可以访问多进程</strong>。这表示QSystemSemaphore是一个重量级的类。因此，使用单一线程或进程时，建议使用QSemaphore。获得资源前，成员函数acquire()始终阻塞。函数release()用于释放资源，且该函数可以设置参数。该函数的参数&gt;1时，释放资源。</p>
<h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p>初始化QSharedMemory时，必须指定一个唯一的标识Key，进程的Key必须保持一致。可以使用setKey来设置。</p>
<h2 id="加载进内存"><a href="#加载进内存" class="headerlink" title="加载进内存"></a>加载进内存</h2><h3 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h3><p>进程A-写</p>
<p>分为下面几步：</p>
<ol>
<li>检测该进程是否连接到共享内存段，如果连接，则将该进程与共享内存段分离。</li>
<li>从系统足够大的内存中得到一个新的共享内存段。</li>
<li>锁定该共享内存段，以阻止第二个对话框进程访问，将缓冲区中的图片复制进共享内存段。</li>
<li>将共享内存段解锁，然后第二个对话框进程就可以访问了。</li>
</ol>
<h3 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">oid <span class="title">Dialog::loadFromFile</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (sharedMemory.<span class="built_in">isAttached</span>())</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">// 将该进程与共享内存段分离</span></span><br><span class="line">        <span class="keyword">if</span> (!sharedMemory.<span class="built_in">detach</span>())</span><br><span class="line">            <span class="built_in">qDebug</span>() &lt;&lt; <span class="string">&quot;Unable to detach from shared memory.&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    QString fileName = QFileDialog::<span class="built_in">getOpenFileName</span>(<span class="number">0</span>, <span class="built_in">QString</span>(), <span class="built_in">QString</span>(),</span><br><span class="line">                                        <span class="built_in">tr</span>(<span class="string">&quot;Images (*.png *.xpm *.jpg)&quot;</span>));</span><br><span class="line">    QImage image;</span><br><span class="line">    <span class="keyword">if</span> (!image.<span class="built_in">load</span>(fileName))</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">qDebug</span>() &lt;&lt; <span class="string">&quot;Selected file is not an image, please select another.&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 将数据加载到共享内存中</span></span><br><span class="line">    QBuffer buffer;</span><br><span class="line">    buffer.<span class="built_in">open</span>(QBuffer::ReadWrite);</span><br><span class="line">    <span class="function">QDataStream <span class="title">out</span><span class="params">(&amp;buffer)</span></span>;</span><br><span class="line">    out &lt;&lt; image;</span><br><span class="line">    <span class="type">int</span> size = buffer.<span class="built_in">size</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 创建共享内存段</span></span><br><span class="line">    <span class="keyword">if</span> (!sharedMemory.<span class="built_in">create</span>(size))</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">qDebug</span>() &lt;&lt; sharedMemory.<span class="built_in">errorString</span>() &lt;&lt; <span class="string">&quot;\n Unable to create shared memory segment.&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    sharedMemory.<span class="built_in">lock</span>();</span><br><span class="line">    <span class="type">char</span> *to = (<span class="type">char</span>*)sharedMemory.<span class="built_in">data</span>();</span><br><span class="line">    <span class="type">const</span> <span class="type">char</span> *from = buffer.<span class="built_in">data</span>().<span class="built_in">data</span>();</span><br><span class="line">    <span class="built_in">memcpy</span>(to, from, <span class="built_in">qMin</span>(sharedMemory.<span class="built_in">size</span>(), size));</span><br><span class="line">    sharedMemory.<span class="built_in">unlock</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="从内存中读取"><a href="#从内存中读取" class="headerlink" title="从内存中读取"></a>从内存中读取</h2><h3 id="说明-1"><a href="#说明-1" class="headerlink" title="说明"></a>说明</h3><p>进程B-读</p>
<p>分为下面几步：</p>
<ol>
<li>将该进程与进程A创建的共享内存段绑定</li>
<li>锁定共享内存段，复制数据到缓冲区，然后写入到QImage中。</li>
<li>将共享内存段解锁，然后将该进程与共享内存段分离。</li>
</ol>
<h3 id="实现-1"><a href="#实现-1" class="headerlink" title="实现"></a>实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">MainWindow::loadFromMemory</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 将共享内存与该进程绑定</span></span><br><span class="line">    <span class="keyword">if</span> (!sharedMemory.<span class="built_in">attach</span>())</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">qDebug</span>() &lt;&lt; <span class="string">&quot;Unable to attach to shared memory segment.&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 从共享内存中读取数据</span></span><br><span class="line">    QBuffer buffer;</span><br><span class="line">    <span class="function">QDataStream <span class="title">in</span><span class="params">(&amp;buffer)</span></span>;</span><br><span class="line">    QImage image;</span><br><span class="line"></span><br><span class="line">    sharedMemory.<span class="built_in">lock</span>();</span><br><span class="line">    buffer.<span class="built_in">setData</span>((<span class="type">char</span>*)sharedMemory.<span class="built_in">constData</span>(), sharedMemory.<span class="built_in">size</span>());</span><br><span class="line">    buffer.<span class="built_in">open</span>(QBuffer::ReadOnly);</span><br><span class="line">    in &gt;&gt; image;</span><br><span class="line">    sharedMemory.<span class="built_in">unlock</span>();</span><br><span class="line"></span><br><span class="line">    sharedMemory.<span class="built_in">detach</span>();</span><br><span class="line">    m_pLabel-&gt;<span class="built_in">setPixmap</span>(QPixmap::<span class="built_in">fromImage</span>(image));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="Qt进程间通信之QProcess"><a href="#Qt进程间通信之QProcess" class="headerlink" title="Qt进程间通信之QProcess"></a>Qt进程间通信之QProcess</h1><h2 id="简述-3"><a href="#简述-3" class="headerlink" title="简述"></a>简述</h2><p>QProcess可以在应用程序内部与其它进程通信，或启动其它应用程序。与在终端机之类的命令输入窗口上使用名称和参数是一样的，可以使用QProcess提供的函数start()启动进程。可以注册QStringList处理进程后的参数。</p>
<h2 id="命令行参数启动"><a href="#命令行参数启动" class="headerlink" title="命令行参数启动"></a>命令行参数启动</h2><p>说明<br>进程A带参启动进程B</p>
<p>一般编写程序时，严格来说，启动外部程序，需要判断版本是debug还是release。否则，有可能会造成错误。<br>判断将要启动的进程是否存在，如果不存在，则启动；否则，不启动。<br>传参：这里我列举的是json格式。<br>实现</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">onSendMessage</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">QString <span class="title">strExe</span><span class="params">(<span class="string">&quot;&quot;</span>)</span></span>;</span><br><span class="line">    <span class="keyword">if</span> (m_pProcess == <span class="literal">NULL</span>)</span><br><span class="line">        m_pProcess = <span class="keyword">new</span> <span class="built_in">QProcess</span>(<span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(QT_DEBUG)</span></span><br><span class="line">    strExe = <span class="string">&quot;ReceiveMessaged.exe&quot;</span>;</span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">    strExe = <span class="string">&quot;ReceiveMessage.exe&quot;</span>;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    <span class="comment">// 判断进程是否存在</span></span><br><span class="line">    QProcess tasklist;</span><br><span class="line">    tasklist.<span class="built_in">start</span>(<span class="string">&quot;tasklist&quot;</span>,</span><br><span class="line">                   <span class="built_in">QStringList</span>() &lt;&lt; <span class="string">&quot;/NH&quot;</span></span><br><span class="line">                   &lt;&lt; <span class="string">&quot;/FO&quot;</span> &lt;&lt; <span class="string">&quot;CSV&quot;</span></span><br><span class="line">                   &lt;&lt; <span class="string">&quot;/FI&quot;</span> &lt;&lt; <span class="built_in">QString</span>(<span class="string">&quot;IMAGENAME eq %1&quot;</span>).<span class="built_in">arg</span>(strExe));</span><br><span class="line">    tasklist.<span class="built_in">waitForFinished</span>();</span><br><span class="line">    QString strOutput = tasklist.<span class="built_in">readAllStandardOutput</span>();</span><br><span class="line">    <span class="keyword">if</span> (!strOutput.<span class="built_in">startsWith</span>(<span class="built_in">QString</span>(<span class="string">&quot;\&quot;%1&quot;</span>).<span class="built_in">arg</span>(strExe)))</span><br><span class="line">    &#123;</span><br><span class="line">        QJsonObject json;</span><br><span class="line"></span><br><span class="line">        json.<span class="built_in">insert</span>(<span class="string">&quot;UserName&quot;</span>, <span class="built_in">QStringLiteral</span>(<span class="string">&quot;╰☆一去、二三里`&quot;</span>));</span><br><span class="line">        json.<span class="built_in">insert</span>(<span class="string">&quot;Password&quot;</span>, <span class="string">&quot;123456&quot;</span>);</span><br><span class="line"></span><br><span class="line">        QJsonDocument document;</span><br><span class="line">        document.<span class="built_in">setObject</span>(json);</span><br><span class="line">        QByteArray byteArray = document.<span class="built_in">toJson</span>(QJsonDocument::Compact);</span><br><span class="line"></span><br><span class="line">        QStringList arguments;</span><br><span class="line">        arguments &lt;&lt; byteArray;</span><br><span class="line">        m_pProcess-&gt;<span class="built_in">startDetached</span>(strExe, arguments);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="命令行读取"><a href="#命令行读取" class="headerlink" title="命令行读取"></a>命令行读取</h2><h3 id="说明-2"><a href="#说明-2" class="headerlink" title="说明"></a>说明</h3><p>进程B-命令行读取</p>
<ol>
<li>在main函数中初始化QApplication以后，获取命令行参数。</li>
<li>命令行参数中包含当前程序的名称、接收的参数等信息。</li>
</ol>
<h3 id="实现-2"><a href="#实现-2" class="headerlink" title="实现"></a>实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">QStringList cmdLineArgs = QCoreApplication::<span class="built_in">arguments</span>();</span><br><span class="line">QMessageBox::<span class="built_in">information</span>(<span class="literal">NULL</span>, <span class="built_in">QStringLiteral</span>(<span class="string">&quot;ReceiveMessage&quot;</span>), cmdLineArgs.<span class="built_in">join</span>(<span class="string">&quot; &quot;</span>));</span><br></pre></td></tr></table></figure>

<h1 id="Qt进程间通信之TCP-IP"><a href="#Qt进程间通信之TCP-IP" class="headerlink" title="Qt进程间通信之TCP&#x2F;IP"></a>Qt进程间通信之TCP&#x2F;IP</h1><h2 id="简述-4"><a href="#简述-4" class="headerlink" title="简述"></a>简述</h2><p>可以通过Qt提供的IPC使用TCP&#x2F;IP，使用QtNetwork模块即可实现，TCP&#x2F;IP在实现应用程序和进程内部通信或与远程进程间的通信方面非常有用。</p>
<p>QtNetwork模块提供的类能够创建基于TCP&#x2F;IP的客户端与服务端应用程序。为实现底层的网络访问，可以使用QTcpSocket、QTcpServer和QUdpSocket，并提供底层网络类。还提供了使用常规协议实现网络操作的QNetworkRequest、QNetworkReply、QNetworkAccessManager。</p>
<h2 id="QtNetwork"><a href="#QtNetwork" class="headerlink" title="QtNetwork"></a>QtNetwork</h2><p>作为使用IPC的方法，TCP&#x2F;IP可以使用多种类进行进程内部和外部的通信。</p>
<p>QtNetwork模块提供的类：</p>
<table>
<thead>
<tr>
<th>类</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>QLocalServer</td>
<td>基于服务器的本地套接字的类</td>
</tr>
<tr>
<td>QLocalSocket</td>
<td>支持本地套接字的类</td>
</tr>
<tr>
<td>QNetworkAccessManager</td>
<td>处理从网络首发收据响应的类</td>
</tr>
<tr>
<td>QSocketNotifier</td>
<td>监控从网络通知消息的类</td>
</tr>
<tr>
<td>QSsl</td>
<td>在所有网络通信上用于SSL认证的类</td>
</tr>
<tr>
<td>QSslSocket</td>
<td>支持通过客户端和服务器端加密的套接字的类</td>
</tr>
<tr>
<td>QTcpServer</td>
<td>基于TCP的服务器端类</td>
</tr>
<tr>
<td>QTcpSocket</td>
<td>TCP套接字</td>
</tr>
<tr>
<td>QUdpSocket</td>
<td>UDP套接字</td>
</tr>
</tbody></table>
<p>除表中所示，Qt提供的QtNetwork模块还支持多种协议。<strong>如果需要实现内部进程间的通信，建议使用QLocalSocket类</strong>。</p>
<p>下面我们来看一个示例，可以在Creator自带的示例中查找QLocalSocket或Local Fortune。</p>
<h2 id="Server"><a href="#Server" class="headerlink" title="Server"></a>Server</h2><p>首先，启动Server，这是必然的，服务端不开启，客户端怎么连接得上呢？</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">server = <span class="keyword">new</span> <span class="built_in">QLocalServer</span>(<span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 告诉服务器监听传入连接的名字。如果服务器当前正在监听，那么将返回false。监听成功返回true，否则为false</span></span><br><span class="line"><span class="keyword">if</span> (!server-&gt;<span class="built_in">listen</span>(<span class="string">&quot;fortune&quot;</span>)) &#123;</span><br><span class="line">    QMessageBox::<span class="built_in">critical</span>(<span class="keyword">this</span>, <span class="built_in">tr</span>(<span class="string">&quot;Fortune Server&quot;</span>),</span><br><span class="line">                        <span class="built_in">tr</span>(<span class="string">&quot;Unable to start the server: %1.&quot;</span>)</span><br><span class="line">                        .<span class="built_in">arg</span>(server-&gt;<span class="built_in">errorString</span>()));</span><br><span class="line">    <span class="built_in">close</span>();</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">fortunes &lt;&lt; <span class="built_in">tr</span>(<span class="string">&quot;You&#x27;ve been leading a dog&#x27;s life. Stay off the furniture.&quot;</span>)</span><br><span class="line">         &lt;&lt; <span class="built_in">tr</span>(<span class="string">&quot;You&#x27;ve got to think about tomorrow.&quot;</span>)</span><br><span class="line">         &lt;&lt; <span class="built_in">tr</span>(<span class="string">&quot;You will be surprised by a loud noise.&quot;</span>)</span><br><span class="line">         &lt;&lt; <span class="built_in">tr</span>(<span class="string">&quot;You will feel hungry again in another hour.&quot;</span>)</span><br><span class="line">         &lt;&lt; <span class="built_in">tr</span>(<span class="string">&quot;You might have mail.&quot;</span>)</span><br><span class="line">         &lt;&lt; <span class="built_in">tr</span>(<span class="string">&quot;You cannot kill time without injuring eternity.&quot;</span>)</span><br><span class="line">         &lt;&lt; <span class="built_in">tr</span>(<span class="string">&quot;Computers are not intelligent. They only think they are.&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 有新客户端进行连接时，发送数据</span></span><br><span class="line"><span class="built_in">connect</span>(server, <span class="built_in">SIGNAL</span>(<span class="built_in">newConnection</span>()), <span class="keyword">this</span>, <span class="built_in">SLOT</span>(<span class="built_in">sendFortune</span>()));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 发送数据</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Server::sendFortune</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 从fortunes中随机取出一段字符串然后进行写入。</span></span><br><span class="line">    QByteArray block;</span><br><span class="line">    <span class="function">QDataStream <span class="title">out</span><span class="params">(&amp;block, QIODevice::WriteOnly)</span></span>;</span><br><span class="line">    out.<span class="built_in">setVersion</span>(QDataStream::Qt_4_0);</span><br><span class="line">    out &lt;&lt; (quint16)<span class="number">0</span>;</span><br><span class="line">    out &lt;&lt; fortunes.<span class="built_in">at</span>(<span class="built_in">qrand</span>() % fortunes.<span class="built_in">size</span>());</span><br><span class="line">    out.<span class="built_in">device</span>()-&gt;<span class="built_in">seek</span>(<span class="number">0</span>);</span><br><span class="line">    out &lt;&lt; (quint16)(block.<span class="built_in">size</span>() - <span class="built_in">sizeof</span>(quint16));</span><br><span class="line"></span><br><span class="line">    <span class="comment">// nextPendingConnection()可以返回下一个挂起的连接作为一个连接的QLocalSocket对象。</span></span><br><span class="line">    QLocalSocket *clientConnection = server-&gt;<span class="built_in">nextPendingConnection</span>();</span><br><span class="line">    <span class="built_in">connect</span>(clientConnection, <span class="built_in">SIGNAL</span>(<span class="built_in">disconnected</span>()),</span><br><span class="line">            clientConnection, <span class="built_in">SLOT</span>(<span class="built_in">deleteLater</span>()));</span><br><span class="line"></span><br><span class="line">    clientConnection-&gt;<span class="built_in">write</span>(block);</span><br><span class="line">    clientConnection-&gt;<span class="built_in">flush</span>();</span><br><span class="line">    clientConnection-&gt;<span class="built_in">disconnectFromServer</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>socket被当做server的孩子创建，这意味着，当QLocalServer对象被销毁时它也会被自动删除。这明显是一个删除对象的好主意，使用完成以后，避免了内存的浪费。</p>
<h2 id="Client"><a href="#Client" class="headerlink" title="Client"></a>Client</h2><p>启动客户端，连接到对应的服务器，如果连接不上，则进行错误处理。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line">socket = <span class="keyword">new</span> <span class="built_in">QLocalSocket</span>(<span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">connect</span>(getFortuneButton, <span class="built_in">SIGNAL</span>(<span class="built_in">clicked</span>()),</span><br><span class="line">        <span class="keyword">this</span>, <span class="built_in">SLOT</span>(<span class="built_in">requestNewFortune</span>()));</span><br><span class="line"><span class="built_in">connect</span>(socket, <span class="built_in">SIGNAL</span>(<span class="built_in">readyRead</span>()), <span class="keyword">this</span>, <span class="built_in">SLOT</span>(<span class="built_in">readFortune</span>()));</span><br><span class="line"><span class="built_in">connect</span>(socket, <span class="built_in">SIGNAL</span>(<span class="built_in">error</span>(QLocalSocket::LocalSocketError)),</span><br><span class="line">        <span class="keyword">this</span>, <span class="built_in">SLOT</span>(<span class="built_in">displayError</span>(QLocalSocket::LocalSocketError)));</span><br><span class="line"></span><br><span class="line"><span class="comment">// 连接到服务器，abort()断开当前连接，重置socket。</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Client::requestNewFortune</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    getFortuneButton-&gt;<span class="built_in">setEnabled</span>(<span class="literal">false</span>);</span><br><span class="line">    blockSize = <span class="number">0</span>;</span><br><span class="line">    socket-&gt;<span class="built_in">abort</span>();</span><br><span class="line">    socket-&gt;<span class="built_in">connectToServer</span>(hostLineEdit-&gt;<span class="built_in">text</span>());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 读取服务器端发送的数据</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Client::readFortune</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 读取接收到的数据</span></span><br><span class="line">    <span class="function">QDataStream <span class="title">in</span><span class="params">(socket)</span></span>;</span><br><span class="line">    in.<span class="built_in">setVersion</span>(QDataStream::Qt_4_0);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (blockSize == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (socket-&gt;<span class="built_in">bytesAvailable</span>() &lt; (<span class="type">int</span>)<span class="built_in">sizeof</span>(quint16))</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        in &gt;&gt; blockSize;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (in.<span class="built_in">atEnd</span>())</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">    QString nextFortune;</span><br><span class="line">    in &gt;&gt; nextFortune;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果当前的数据和收到的数据相同，则重新请求一次，因为是随机的字符串，所以肯定不会每次都相同。</span></span><br><span class="line">    <span class="keyword">if</span> (nextFortune == currentFortune) &#123;</span><br><span class="line">        QTimer::<span class="built_in">singleShot</span>(<span class="number">0</span>, <span class="keyword">this</span>, <span class="built_in">SLOT</span>(<span class="built_in">requestNewFortune</span>()));</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    currentFortune = nextFortune;</span><br><span class="line">    statusLabel-&gt;<span class="built_in">setText</span>(currentFortune);</span><br><span class="line">    getFortuneButton-&gt;<span class="built_in">setEnabled</span>(<span class="literal">true</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 发生错误时，进行错误处理</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Client::displayError</span><span class="params">(QLocalSocket::LocalSocketError socketError)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (socketError) &#123;</span><br><span class="line">    <span class="keyword">case</span> QLocalSocket::ServerNotFoundError:</span><br><span class="line">        QMessageBox::<span class="built_in">information</span>(<span class="keyword">this</span>, <span class="built_in">tr</span>(<span class="string">&quot;Fortune Client&quot;</span>),</span><br><span class="line">                                 <span class="built_in">tr</span>(<span class="string">&quot;The host was not found. Please check the &quot;</span></span><br><span class="line">                                    <span class="string">&quot;host name and port settings.&quot;</span>));</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> QLocalSocket::ConnectionRefusedError:</span><br><span class="line">        QMessageBox::<span class="built_in">information</span>(<span class="keyword">this</span>, <span class="built_in">tr</span>(<span class="string">&quot;Fortune Client&quot;</span>),</span><br><span class="line">                                 <span class="built_in">tr</span>(<span class="string">&quot;The connection was refused by the peer. &quot;</span></span><br><span class="line">                                    <span class="string">&quot;Make sure the fortune server is running, &quot;</span></span><br><span class="line">                                    <span class="string">&quot;and check that the host name and port &quot;</span></span><br><span class="line">                                    <span class="string">&quot;settings are correct.&quot;</span>));</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> QLocalSocket::PeerClosedError:</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        QMessageBox::<span class="built_in">information</span>(<span class="keyword">this</span>, <span class="built_in">tr</span>(<span class="string">&quot;Fortune Client&quot;</span>),</span><br><span class="line">                                 <span class="built_in">tr</span>(<span class="string">&quot;The following error occurred: %1.&quot;</span>)</span><br><span class="line">                                 .<span class="built_in">arg</span>(socket-&gt;<span class="built_in">errorString</span>()));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    getFortuneButton-&gt;<span class="built_in">setEnabled</span>(<span class="literal">true</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<hr>

        
            <div class="donate-container">
    <div class="donate-button">
        <button id="donate-button">赞赏</button>
    </div>
    <div class="donate-img-container hide" id="donate-img-container">
        <img id="donate-img" src="" data-src="/myblog/img/donate.jpg">
        <p> 感谢鼓励 </p>
    </div>
</div>
        
        <br />
        <div id="comment-container">
        </div>
        <div id="disqus_thread"></div>
        <div id="lv-container"></div>
        <div class="giscus"></div>
    </div>
</div>

    </div>
</div>


<footer class="footer">
    <ul class="list-inline text-center">
        
        

        

        

        
        <li>
            <a target="_blank"  href="https://github.com/samuel-24276">
                            <span class="fa-stack fa-lg">
                                <i class="iconfont icon-github"></i>
                            </span>
            </a>
        </li>
        

        

    </ul>
    
    <p>
        <span>/</span>
        
        <span><a target="_blank" rel="noopener" href="https://github.com/samuel-24276">samuel-24276&#39;s Page</a></span>
        <span>/</span>
        
        <span><a target="_blank" rel="noopener" href="https://beian.miit.gov.cn/">北京-未备案</a></span>
        <span>/</span>
        
        <span><a href="#">返回顶部</a></span>
        <span>/</span>
        
    </p>
    
    <p>
        <span id="busuanzi_container_site_pv">
            <span id="busuanzi_value_site_pv"></span>PV
        </span>
        <span id="busuanzi_container_site_uv">
            <span id="busuanzi_value_site_uv"></span>UV
        </span>
        Created By <a target="_blank" rel="noopener" href="https://hexo.io/">Hexo</a>  Theme <a target="_blank" rel="noopener" href="https://github.com/aircloud/hexo-theme-aircloud">AirCloud</a></p>
</footer>




</body>

<script>
    // We expose some of the variables needed by the front end
    window.hexo_search_path = "search.json"
    window.hexo_root = "/myblog/"
    window.isPost = true
</script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

<script src="/myblog/js/index.js"></script>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>






    <script type="text/javascript">
       (function() {
           if (typeof LivereTower === 'function') { return; }

           var j, d = document.getElementById('lv-container');

           d.setAttribute('data-id','city');
           d.setAttribute('data-uid' , 'MTAyMC80OTA5OC8yNTU5Mw==');

           j = document.createElement('script');
           j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
           j.async = true;

           d.appendChild(j);
       })();
    </script>
    <noscript>为正常使用来必力评论功能请激活JavaScript</noscript>
    </div>

</html>
